package com.rds.mongodb.service.impl;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSDownloadStream;
import com.mongodb.client.gridfs.model.GridFSFile;
import com.rds.mongodb.entity.FileDocument;
import com.rds.mongodb.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Field;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsResource;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.List;
import java.util.Optional;

/**
 * 文件上传下载服务实现类
 *
 * @author Lin Zemin
 * @date 2020-10-28
 */
@Slf4j
@Service
public class FileServiceImpl implements FileService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private GridFsTemplate gridFsTemplate;

    @Autowired
    private GridFSBucket gridFsBucket;

    @Override
    public FileDocument saveFile(FileDocument file) {
        file = mongoTemplate.save(file);
        return file;
    }

    @Override
    public String uploadFileToGridFs(InputStream inputStream , String contentType){
        String gridfsId = IdUtil.simpleUUID();
        //将文件存储进GridFS中
        gridFsTemplate.store(inputStream, gridfsId , contentType);
        return gridfsId;
    }

    @Override
    public void removeFile(String id) {
        //根据id查询文件
        FileDocument fileDocument = mongoTemplate.findById(id , FileDocument.class);
        if(fileDocument!=null){
            //根据文件ID删除fs.files和fs.chunks中的记录
            Query deleteFileQuery = new Query().addCriteria(Criteria.where("filename").is(fileDocument.getGridfsId()));
            gridFsTemplate.delete(deleteFileQuery);
            //删除集合fileDocment中的数据
            Query deleteQuery=new Query(Criteria.where("id").is(id));
            mongoTemplate.remove(deleteQuery,FileDocument.class);
        }
    }

    @Override
    public Optional<FileDocument> getFileById(String id){
        FileDocument fileDocument = mongoTemplate.findById(id , FileDocument.class);
        if(fileDocument != null){
            Query gridQuery = new Query().addCriteria(Criteria.where("filename").is(fileDocument.getGridfsId()));
            try {
                //根据id查询文件
                GridFSFile fsFile = gridFsTemplate.findOne(gridQuery);
                //打开流下载对象
                if(fsFile != null) {
                    GridFSDownloadStream gridFsDownloadStream = gridFsBucket.openDownloadStream(fsFile.getObjectId());
                    if(gridFsDownloadStream.getGridFSFile().getLength() > 0){
                        //获取流对象
                        GridFsResource resource = new GridFsResource(fsFile, gridFsDownloadStream);
                        //获取数据
                        fileDocument.setContent(IoUtil.readBytes(resource.getInputStream()));
                        return Optional.of(fileDocument);
                    }
                }

            }catch (IOException ex){
                ex.printStackTrace();
            }
        }
        return Optional.empty();
    }

    @Override
    public List<FileDocument> listFilesByPage(int pageIndex, int pageSize) {
        Query query = new Query().with(Sort.by(Sort.Direction.DESC, "uploadDate"));
//        long skip = (pageIndex -1) * pageSize;
//        query.skip(skip);
//        query.limit(pageSize);
//        Field field = query.fields();
//        field.exclude("content");
        return mongoTemplate.find(query , FileDocument.class);

    }

    @Override
    public void downLoadFile(HttpServletResponse response, String id) {
        //通过gridFsTemplate模版获取gridFSFile对象 根据Id查询单个对象
        FileDocument fileDocument = mongoTemplate.findById(id , FileDocument.class);
        if(fileDocument != null) {
            Query gridQuery = new Query().addCriteria(Criteria.where("filename").is(fileDocument.getGridfsId()));
            //根据id查询文件
            GridFSFile gridFsFile = gridFsTemplate.findOne(gridQuery);

            if(gridFsFile != null) {
                //根据文件ObjectId查出文件对象
                GridFSDownloadStream gridFsDownloadStream = gridFsBucket.openDownloadStream(gridFsFile.getObjectId());
                //获取文件的下载流
                GridFsResource gridFsResource = new GridFsResource(gridFsFile, gridFsDownloadStream);

                byte[] buffer = new byte[1024];
                //输出流
                OutputStream os = null;
                InputStream fis = null;
                try {
                    fis = gridFsResource.getInputStream();
                    BufferedInputStream bis = new BufferedInputStream(fis);
                    response.setContentType("application/octet-stream");
                    response.setHeader("content-type", "application/octet-stream");
                    response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileDocument.getName(),"UTF-8"));
                    os = response.getOutputStream();
                    int i = bis.read(buffer);
                    while (i != -1) {
                        os.write(buffer);
                        i = bis.read(buffer);
                    }
                } catch (Exception e) {
                    log.error(e.getMessage(),e);
                } finally {
                    IoUtil.close(fis);
                    IoUtil.close(os);
                }
            }
        }

    }

}
